import os
import re
import uuid
from urllib.parse import quote

from django.conf import settings
from django.core.cache import caches
from django.db import IntegrityError
from django.http import HttpRequest, JsonResponse, HttpResponse, StreamingHttpResponse
from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_exempt

from vote.captcha import Captcha
from vote.models import Subject, Teacher, User, LoginLog
from vote.myforms import RegisterForm, LoginForm
from vote.utils import random_captcha_text, random_mobile_code, send_code_by_sms


def send_mobile_code(request, tel):
    """发送短信验证码"""
    code = random_mobile_code()
    if tel in caches['mobile']:
        data = {'code': 403, 'message': '请不要在120秒内重复发送'}
    else:
        result = send_code_by_sms(tel, code)
        if result['error'] == 0:
            # 将手机验证码保存到缓存中
            caches['mobile'].set(tel, code, timeout=120)
            data = {'code': 200, 'message': '短信验证码已发送'}
        else:
            data = {'code': 404, 'message': '短信验证码服务暂时无法使用'}
    return JsonResponse(data)


def download_pdf(request):
    """打开PDF文件"""
    path = os.path.dirname(os.path.abspath(__file__))
    path = os.path.join(path, 'resources/Docker入门教程.pdf')
    file_stream = open(path, 'rb')
    file_iter = iter(lambda: file_stream.read(1024), b'')
    resp = StreamingHttpResponse(file_iter, content_type='application/pdf')
    filename = quote('Docker入门教程.pdf')
    resp['content-disposition'] = f'inline; filename="{filename}"'
    return resp


def download_excel(request):
    """下载Excel文件"""
    path = os.path.dirname(os.path.abspath(__file__))
    path = os.path.join(path, 'resources/老师信息登记表.xlsx')
    with open(path, 'rb') as file_stream:
        buffer = file_stream.read()
    resp = HttpResponse(buffer, content_type='application/vnd.ms-excel')
    filename = quote('老师信息登记表.xlsx')
    resp['content-disposition'] = f'attachment; filename="{filename}"'
    return resp


def get_captcha(request):
    """验证码"""
    captcha_text = random_captcha_text()
    request.session['captcha'] = captcha_text
    image_data = Captcha.instance().generate(captcha_text)
    return HttpResponse(image_data, content_type='image/png')


def login(request: HttpRequest):
    """登录"""
    hint, backurl = '', request.GET.get('backurl', '/')
    if request.method == 'POST':
        backurl = request.POST.get('backurl', '/')
        form = LoginForm(request.POST)
        if form.is_valid():
            captcha_from_user = form.cleaned_data['captcha']
            captcha_from_sess = request.session.get('captcha', '')
            if captcha_from_sess.lower() != captcha_from_user.lower():
                hint = '请输入正确的验证码'
            else:
                username = form.cleaned_data['username']
                password = form.cleaned_data['password']
                user = User.objects.filter(username=username, password=password).first()
                if user:
                    print(user.photo.url)
                    request.session['user'] = user
                    login_log = LoginLog()
                    login_log.ip_addr = request.META['REMOTE_ADDR']
                    login_log.user = user
                    login_log.save()
                    # backurl = backurl or '/'
                    return redirect(backurl)
                else:
                    hint = '用户名或密码错误'
        else:
            hint = '请输入有效的登录信息'
    return render(request, 'login.html', {'hint': hint, 'backurl': backurl})


def register(request: HttpRequest):
    """注册"""
    hint = ''
    if request.method == 'POST':
        try:
            form = RegisterForm(data=request.POST, files=request.FILES)
            if form.is_valid():
                tel = form.cleaned_data['tel']
                code_from_cache = caches['mobile'].get(tel)
                code_from_user = form.cleaned_data['mobilecode']
                if code_from_cache == code_from_user:
                    form.save()
                    return render(request, 'login.html', {'hint': '注册成功，请登录', 'backurl': '/'})
                else:
                    hint = '无效的手机验证码'
            else:
                hint = '请输入有效的注册信息'
        except IntegrityError:
            hint = '用户已被注册，请更换其他的用户名'
    return render(request, 'register.html', {'hint': hint})


def logout(request):
    """注销"""
    request.session.flush()
    return redirect('/')


def show_subjects(request):
    """查看所有学科"""
    subjects = Subject.objects.all()
    resp = render(request, 'subject.html', {'subjects': subjects})
    return resp


def show_teachers(request):
    """查看指定学科的老师"""
    try:
        sno = int(request.GET['sno'])
        subject = Subject.objects.get(no=sno)
        teachers = Teacher.objects.filter(subject__no=sno)
        return render(request, 'teacher.html', {'subject': subject, 'teachers': teachers})
    except (KeyError, ValueError, Subject.DoesNotExist):
        return redirect('/')


def praise_or_criticize(request: HttpRequest):
    """投票"""
    if 'user' in request.session:
        try:
            tno = int(request.GET.get('tno', '0'))
            teacher = Teacher.objects.get(no=tno)
            if request.path.startswith('/vote/praise'):
                teacher.good_count += 1
            else:
                teacher.bad_count += 1
            teacher.save()
            data = {'code': 200, 'message': '操作成功'}
        except (ValueError, Teacher.DoesNotExist):
            data = {'code': 404, 'message': '操作失败'}
    else:
        data = {'code': 401, 'message': '请先登录'}
    return JsonResponse(data)


@csrf_exempt
def upload_picture(request):
    data = []
    for image_file in request.FILES.values():
        if image_file:
            ext = os.path.splitext(image_file.name)[-1]
            filename = uuid.uuid1().hex + ext
            url = f'/media/{filename}'
            path = os.path.join(settings.MEDIA_ROOT, filename)
            with open(path, 'wb') as file_stream:
                file_stream.write(image_file.read())
            data.append(url)
    return JsonResponse({'errno': 0, 'data': data})


def show_user(request):
    user = request.session.get('user', None)
    if user:
        intro = user.intro
        pattern = re.compile(r'[\r\n]')
        intro = pattern.sub('', intro)
        print(intro)
        return render(request, 'user.html', {'intro': intro})
    else:
        return redirect('a:login')
